#include "VertexBufferGL.hpp"

#include <stdexcept>

namespace Graphics
{
	using namespace RevEng;
	using namespace RevEng::Math;

	VertexBufferVBO::VertexBufferVBO() : m_nId(0), m_pVerts(NULL), m_nCount(0), m_bLocked(false)
	{
		glGenBuffersARB(1, &m_nId);
	}


	VertexBufferVBO::~VertexBufferVBO()
	{
		if (m_pVerts)
		{
			delete[] m_pVerts;
			m_pVerts = NULL;
			m_nCount = 0;
		}

		if (m_nId != 0)
		{
			glDeleteBuffersARB(1, &m_nId);
			m_nId = 0;
		}
	}


	UInt32 VertexBufferVBO::GetVertexCount() const
	{
		return m_nCount;
	}


	void VertexBufferVBO::SetVertexCount( UInt32 Count )
	{
		GLenum nError=0;

		if (Count > 0 && m_nCount!=Count)
		{
			m_nCount = Count;

			if (m_pVerts)
			{
				delete m_pVerts;
				m_pVerts = NULL;
			}

			if (m_pVerts==NULL)
				m_pVerts = new Vertex[Count];

			//Set the buffer format, for now.
			glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nId);
			nError = glGetError();

			glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_nCount*sizeof(Vertex), NULL, GL_DYNAMIC_DRAW_ARB);
			nError = glGetError();
		}
	}


	void* VertexBufferVBO::Lock()
	{
		if (m_pVerts == NULL)
			throw std::runtime_error("Call IVertexBuffer::SetVertexCount first.");

		if (m_bLocked == true)
			throw std::runtime_error("Buffer already locked.");

		m_bLocked = true;
		return m_pVerts;
	}


	void VertexBufferVBO::Unlock()
	{
		if (m_bLocked == false)
			throw std::runtime_error("Call IVertexBuffer::Lock first.");

		glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nId);
		glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, m_nCount*sizeof(Vertex), m_pVerts);

		m_bLocked = false;
	}
}
